package lerry.nape.body;

import nape.constraint.PivotJoint;
import nape.dynamics.InteractionGroup;
import nape.geom.GeomPoly;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.geom.Vec2List;
import nape.phys.Body;
import nape.phys.BodyList;
import nape.phys.BodyType;
import nape.phys.Compound;
import nape.shape.Edge;
import nape.shape.Polygon;
import nape.shape.Shape;
import nape.space.Space;
/**
 * ...
 * @author lxq
 */
class SoftBody {
	private var soft:Compound;
	public function new(geomPoly:GeomPoly,position:Vec2=null,cellSize:UInt=30,thickness:UInt=10,frequency:UInt=30,damping:UInt=10,ignore:Bool=true) {
		var bodies:BodyList=new BodyList();
			var inVec2s:Vec2List=new Vec2List();
			var outVec2s:Vec2List=new Vec2List();
			if(position!=null){
				var trans:Mat23=new Mat23(1,0,0,1,position.x,position.y);
				geomPoly.transform(trans);
			}
			soft=new Compound();
			var inner:GeomPoly=geomPoly.inflate(-thickness);
			var start:Vec2=geomPoly.current();
			var current:Vec2,next:Vec2;
			var icurrent:Vec2,inext:Vec2;
			
			var group:InteractionGroup=new InteractionGroup(ignore);
			
			do {
				current=geomPoly.current();
				geomPoly.skipForward(1);
				next=geomPoly.current();
				
				icurrent=inner.current();
				inner.skipForward(1);
				inext=inner.current();
				
				var len:Vec2=next.sub(current);
				var ilen:Vec2=inext.sub(icurrent);
				
				var max:Float=Math.max(len.length,ilen.length);
				var numSegments:UInt=Math.ceil(max / cellSize);
				var cell:Float=(1 / numSegments);
				var i:UInt;
				for(i in 0...numSegments) {
					var b:Body=new Body(BodyType.DYNAMIC);
					var outVec:Vec2=current.addMul(len,cell * i);
					var inVec:Vec2=icurrent.addMul(ilen,cell * i);
					b.shapes.add(new Polygon([outVec,current.addMul(len,cell * (i + 1),true),icurrent.addMul(ilen,cell * (i + 1),true),inVec]));
					b.compound=soft;
					bodies.add(b);
					inVec2s.add(inVec);
					outVec2s.add(outVec);
					b.group=group;
				
					b.align();
				}
				
				len.dispose();
				ilen.dispose();
				
			} while (geomPoly.current() != start);
			
			var j:Int;
			var blen:Int=bodies.length;
			for(j in 0...blen) {
				var leftSegment:Body=bodies.at(j);
				var rightSegment:Body;
				j== blen - 1 ? rightSegment=bodies.at(0) : rightSegment=bodies.at(j + 1);
				current=outVec2s.at(j);
				var pivot:PivotJoint=new PivotJoint(leftSegment,rightSegment,leftSegment.worldPointToLocal(current,true),rightSegment.worldPointToLocal(current,true));
				current.dispose();
				pivot.compound=soft;
				
				current=inVec2s.at(j);
				pivot=new PivotJoint(leftSegment,rightSegment,leftSegment.worldPointToLocal(current,true),rightSegment.worldPointToLocal(current,true));
				current.dispose();
				pivot.compound=soft;
				pivot.stiff=false;
				pivot.frequency=30;
				pivot.damping=10;
				pivot.ignore=ignore;
			}
			
			inner.clear();
	}
	
	private function set_space(value:Space):Space {
		soft.space = value;
		return space = value;
	}
	public var space(null, set_space):Space;
	
}